<?php
declare(strict_types=1);

namespace App\Services\Tools\AdapaySdk;

use App\Services\Tools\AdapaySdk\Dto\PaymentDto;
use App\Services\Tools\AdapaySdk\Exception\PaymentRequestExctption;
use JsonException;
use Symfony\Component\HttpClient\HttpClient;
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;

class Payment
{
    private $kernel;

    /**
     * @param Kernel $kernel
     */
    public function __construct(Kernel $kernel)
    {
        $this->kernel = $kernel;
    }

    /**
     * @throws PaymentRequestExctption
     * @throws RedirectionExceptionInterface
     * @throws ClientExceptionInterface
     * @throws JsonException
     * @throws TransportExceptionInterface
     * @throws ServerExceptionInterface
     */
    public function aliPay(string $orderNo, string $payAmt, string $title, string $desc, string $deviceIp): PaymentDto
    {
        $params = [
            'order_no'    => $orderNo,
            'app_id'      => $this->kernel->getAppId(),
            'pay_channel' => 'alipay', //渠道
            'pay_amt'     => sprintf("%.2f", $payAmt),
            'goods_title' => $title,
            'goods_desc'  => $desc,
            'device_info' => ['device_ip' => $deviceIp],
            'currency'    => 'cny',
            'sign_type'   => 'RSA2',
            'notify_url'  => $this->kernel->getNotifyUrl()
        ];
        $reqUrl = Api::BASE_URL . Api::PAYMENT_CREATE;
        $header['sdk_version'] = Api::SDK_VERSION;
        $header['authorization'] = $this->kernel->getApiKeyLive();
        $header['signature'] = $this->kernel->sign($reqUrl, json_encode($params, JSON_THROW_ON_ERROR));

        $httpClient = HttpClient::create(['verify_peer' => false, 'verify_host' => false]);
        $response = $httpClient->request('POST', $reqUrl, [
            'json'    => $params,
            'headers' => $header
        ]);
        $content = $response->getContent(false);
        $arrayData = json_decode($content, true, 512, JSON_THROW_ON_ERROR);
        $businessData = json_decode($arrayData['data'], true, 512, JSON_THROW_ON_ERROR);

        if ($response->getStatusCode() === 200 && !$this->kernel->verifySign($arrayData['data'], $arrayData['signature'])) {
            throw new PaymentRequestExctption('支付平台api响应验签失败' . "/n" . $content);
        }

        if ($response->getStatusCode() !== 200) {
            throw new PaymentRequestExctption('支付调用失败，详细信息：' . "/n" . $content);
        }

        $paymentDto = new PaymentDto();
        $paymentDto->expend = $businessData['expend'] ?? [];
        $paymentDto->app_id = $businessData['app_id'] ?? '';
        $paymentDto->created_time = $businessData['created_time'] ?? '';
        $paymentDto->id = $businessData['id'] ?? '';
        $paymentDto->object = $businessData['object'] ?? '';
        $paymentDto->order_no = $businessData['order_no'] ?? '';
        $paymentDto->party_order_id = $businessData['party_order_id'] ?? '';
        $paymentDto->pay_amt = $businessData['pay_amt'] ?? '';
        $paymentDto->pay_channel = $businessData['pay_channel'] ?? '';
        $paymentDto->prod_mode = $businessData['prod_mode'] ?? '';
        $paymentDto->query_url = $businessData['query_url'] ?? '';
        $paymentDto->status = $businessData['status'] ?? '';
        if (!$paymentDto->validate()) {
            throw new PaymentRequestExctption('支付调用失败，详细信息：' . "/n" . $content);
        }
        return $paymentDto;
    }
}